package com.yuyou.fn.educational.service.impl;

import com.github.wens.mybatisplus.examples.Example;
import com.google.common.base.Optional;
import com.google.common.cache.LoadingCache;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.lang.Tuple2;
import com.yuyou.fn.common.util.CacheUtils;
import com.yuyou.fn.common.util.TimeUtils;
import com.yuyou.fn.educational.entity.*;
import com.yuyou.fn.educational.service.*;
import com.yuyou.fn.platform.entity.AreaTeam;
import com.yuyou.fn.platform.service.IAreaTeamService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.stream.Stream;

/**
 * AttendClassLecture 表数据服务层接口实现类
 */
@Service
public class RegRuleServiceImpl implements IRegRuleService {


    @Resource
    private IAreaTeamService areaTeamService;

    @Resource
    private IPeriodService periodService;

    @Resource
    private IStudentRegService studentRegService;

    @Resource
    private IStudentMeasureScoreService studentMeasureScoreService;

    @Resource
    private IMeasurementService measurementService;

    @Resource
    private IOnlineTestService onlineTestService;

    @Resource
    private IExternalMeasureScoreService externalMeasureScoreService;

    private LoadingCache<String, com.google.common.base.Optional<Period>> periodCache;

    @Value("${dev.env}")
    private boolean dev ;

    @PostConstruct
    public void init() {
        periodCache = CacheUtils.buildCache(60, (key) -> {
            String[] items = key.split("\\|");
            AreaTeam areaTeam = areaTeamService.findAreaTeamByName(items[0]);
            if (areaTeam == null) {
                return null;
            }
            return periodService.findPeriodByAreaTeamIdPeriodName(areaTeam.getAreaTeamId(), items[1]);
        });
    }

    @Override
    public Map<Long, Result> regRule(Student student, List<CourseClass> courseClasses, int regFrom) {

        Stream<CourseClass> stream = courseClasses.stream();

        if (courseClasses.size() > 2) {
            stream = stream.parallel();
        }

        Map<Long, Result> resultMap = new ConcurrentHashMap<>();
        stream.map(courseClass -> Tuple2.of(courseClass.getClassId(), doCheckRegRule(student, courseClass, regFrom)))
                .forEach(r -> {
                    resultMap.put(r.getFirst(), r.getSecond());
                });

        return resultMap;
    }

    private Result doCheckRegRule(Student student, CourseClass courseClass, int regFrom) {

        Result result = checkNeedTest(student, courseClass, regFrom == 1);

        if (result.getCode() != 200) {
            return result;
        }

        return checkRegEnable(student, courseClass, regFrom == 1);
    }

    @Override
    public Result checkRegEnable(Student student, CourseClass courseClass, boolean isOnline) {
        //2019广州寒春报读，2018-11-10 08:00:00 开始报名，2018-11-10 00:00:00~2018-11-26 08:00:00 2018年秋季在读生报读

        if(dev){
            return new Result(200,null);
        }


        if ("广州区域".equals(courseClass.getAreaTeamName()) && ("2019暑假2019秋季".contains(courseClass.getPeriodName())) ) {

            if( "高二高三".contains(courseClass.getGradeName()) ){
                Date beginRegDate = TimeUtils.parse("2019-04-20 08:00:00", "yyyy-MM-dd HH:mm:ss");
                Date now = TimeUtils.now();
                if (now.before(beginRegDate)) {
                    return new Result(500, "4.20 （周六）8:00开放报名，敬请期待！");
                }

                if (  now.before(TimeUtils.parse("2019-05-06 08:00:00", "yyyy-MM-dd HH:mm:ss"))) {
                    Optional<Period> periodOptional = null;
                    try {
                        periodOptional = periodCache.get("广州区域|2019春季");
                    } catch (ExecutionException e) {
                        //
                    }
                    if (periodOptional.isPresent()) {
                        Example<StudentReg> example = StudentReg.createExample();
                        Example.Criteria criteria = example.createCriteria();
                        criteria.andEqualTo("studentId", student.getStudentId());
                        criteria.andEqualTo("periodId", periodOptional.get().getPeriodId());
                        criteria.andEqualTo("regStatus", 0);
                        criteria.andEqualTo("chargingStatus", 2);
                        //8人班不用判断春季在读
                        if ( courseClass.getQuota() != 8 && studentRegService.countByExample(example) == 0) {
                            return new Result(600, "【" + courseClass.getClassName() + "】当前只仅限于春季在读生报读，请先报2019春季课程或咨询校区工作人员，谢谢！");
                        }
                    }
                }
            }else if("高一".contains(courseClass.getGradeName())){
                Date beginRegDate = TimeUtils.parse("2019-05-01 08:00:00", "yyyy-MM-dd HH:mm:ss");
                Date now = TimeUtils.now();
                if (now.before(beginRegDate)) {
                    return new Result(500, "5.1 （周三）8:00开放报名，敬请期待！");
                }
            }


        }

        return new Result(200, null);
    }

    @Override
    public Result checkNeedTest(Student student, CourseClass courseClass, boolean isOnline) {

        Measurement measurement = needTest(student, courseClass.getPeriodId(), courseClass.getGradeId(), courseClass.getSubjectId(), courseClass.getLevel(), courseClass.getCampusId());
        if (measurement != null) {
            if (!measurementService.isInWhiltelist(measurement, student.getStudentId()) &&
                    !studentMeasureScoreService.checkPass(student.getStudentId(), measurement.getGradeId(), measurement.getSubjectId(), measurement.getLevel(), measurement.getCampusIds(), measurement.getPassingScore())
            ) {

                if (isOnline) {

                    boolean pass = false;

                    if (measurement.getExternalScoreType() != null && measurement.getExternalScoreType() != 0) {
                        pass = externalMeasureScoreService.checkPass(student.getStudentId(), measurement.getGradeId(), measurement.getSubjectId(), measurement.getExternalScoreType(), measurement.getExternalPassingScore(), isOnline);
                    }

                    if (!pass) {

                        OnlineTest onlineTest;
                        try {
                            int asFlag = getAsFlag(courseClass);
                            onlineTest = onlineTestService.generateOnlineTestForStudent(courseClass.getCampusId(), student.getStudentId(), measurement.getMeasurementId(), asFlag);
                        } catch (BusException e) {
                            return new Result(401, "您好，学员" + student.getName() + "所报读的课程“" + courseClass.getClassAliasName() + "”需要学前诊断，请到校区进行咨询及诊断。");
                        }
                        return new Result(400, "needTest-" + onlineTest.getOnlineTestId() + "|" + student.getStudentId() + "|" + student.getName() + "|" + courseClass.getClassAliasName());
                    }

                } else {
                    return new Result(401, "您好，学员" + student.getName() + "所报读的课程“" + courseClass.getClassName() + "”需要学前诊断，请到校区进行咨询及诊断。");
                }

            }
        }

        return new Result(200, null);
    }

    /**
     * 判断文理科
     *
     * @param courseClass
     * @return
     */
    private int getAsFlag(CourseClass courseClass) {

        if (courseClass.getSubjectId().equals(20l)) {//数学

            String className = courseClass.getClassName();

            if (className.contains("文科") || className.contains("文数")) {
                return 1;
            } else if (className.contains("理科") || className.contains("理数")) {
                return 2;
            }
        }

        return 0;
    }

    private Measurement needTest(Student student, Long periodId, Long gradeId, Long subjectId, Integer level, Long campusId) {
        List<Measurement> measurements = measurementService.findMeasureByPeriodIdFromCache(periodId);
        if (measurements == null || measurements.size() == 0) {
            return null;
        }

        Measurement matchMeasurement = null;
        for (Measurement measurement : measurements) {

            if (campusId == null) {
                matchMeasurement = measurement;
                break;
            }

            if (StringUtils.isEmpty(measurement.getCampusIds()) || measurement.getCampusIds().contains(String.valueOf(campusId))) {
                if (measurement.getGradeId().equals(gradeId) && measurement.getSubjectId().equals(subjectId) && measurement.getLevel().equals(level)) {
                    matchMeasurement = measurement;
                    break;
                }
            }

        }


        return matchMeasurement;
    }

}